#include "rs232.h"
#include <chrono>
static constexpr std::chrono::seconds kWriteTimeout = std::chrono::seconds{5};

RS232::RS232(QObject *parent)
    : Device{parent},
    m_timer(new QTimer(this)),
    //! [1]
    m_serial(new QSerialPort(this))
{
    connect(m_serial, &QSerialPort::errorOccurred, this, &RS232::handleError);
    connect(m_timer, &QTimer::timeout, this, &RS232::handleWriteTimeout);
    m_timer->setSingleShot(true);
    connect(m_serial, &QSerialPort::readyRead, this, &RS232::readData);
    connect(m_serial, &QSerialPort::bytesWritten, this, &RS232::handleBytesWritten);
}

RS232::~RS232(){
    closeSerialPort();
}

int RS232::nPort() const
{
    return m_nPort;
}

void RS232::setNPort(int newNPort)
{
    m_nPort = newNPort;
}

int RS232::nBaud() const
{
    return m_nBaud;
}

void RS232::setNBaud(int newNBaud)
{
    m_nBaud = newNBaud;
}

int RS232::nCheck() const
{
    return m_nCheck;
}

void RS232::setNCheck(int newNCheck)
{
    m_nCheck = newNCheck;
}

int RS232::nDatabits() const
{
    return m_nDatabits;
}

void RS232::setNDatabits(int newNDatabits)
{
    m_nDatabits = newNDatabits;
}

int RS232::nStopbits() const
{
    return m_nStopbits;
}

void RS232::setNStopbits(int newNStopbits)
{
    m_nStopbits = newNStopbits;
}

void RS232::initDevice(){
    openSerialPort();
}

void RS232::writeXML(QXmlStreamWriter& writer){
    // 写入当前操作的信息
    writer.writeStartElement("RS232");
    writer.writeAttribute(QStringLiteral("id"),m_strID);

    writer.writeTextElement("port", QString::number(m_nPort));
    writer.writeTextElement("baud", QString::number(m_nBaud));
    writer.writeTextElement("check", QString::number(m_nCheck));
    writer.writeTextElement("databits", QString::number(m_nDatabits));
    writer.writeTextElement("stopbits", QString::number(m_nStopbits));
    writer.writeEndElement();  // 结束当前操作的元素
}
// 有点问题
void RS232::readFromXML(QXmlStreamReader& reader){
    QXmlStreamAttributes attributes = reader.attributes();
    if(attributes.hasAttribute("id")) {
        m_strID = attributes.value("id").toString();
    }

    QXmlStreamReader::TokenType token = reader.readNext();
    while (!(reader.tokenType() == QXmlStreamReader::EndElement &&
             reader.name() == QStringLiteral("RS232"))) {

        if (reader.name() == QStringLiteral("port")) {
            m_nPort = reader.readElementText().toInt();
        }else if (reader.name() == QStringLiteral("baud")) {
            m_nBaud = reader.readElementText().toInt();
        }else if (reader.name() == QStringLiteral("check")) {
            m_nCheck = reader.readElementText().toInt();
        }else if (reader.name() == QStringLiteral("databits")) {
            m_nDatabits = reader.readElementText().toInt();
        }else if (reader.name() == QStringLiteral("stopbits")) {
            m_nStopbits = reader.readElementText().toInt();
        }

        reader.readNext();
    }
}

void RS232::openSerialPort()
{
    /*m_serial->setPortName(QString("COM%1").arg(m_nPort));
    m_serial->setBaudRate(m_nBaud);
    m_serial->setDataBits(QSerialPort::Data8);
    m_serial->setParity(QSerialPort::NoParity);
    m_serial->setStopBits(QSerialPort::OneStop);
    m_serial->setFlowControl(QSerialPort::NoFlowControl);*/
    m_serial->setPortName("COM4");
    m_serial->setBaudRate(9600);
    m_serial->setDataBits(QSerialPort::Data8);
    m_serial->setParity(QSerialPort::NoParity);
    m_serial->setStopBits(QSerialPort::OneStop);
    m_serial->setFlowControl(QSerialPort::NoFlowControl);
    if (m_serial->open(QIODevice::ReadWrite)) {
        qDebug() << QString("Open SerialPort Successful!");
    } else {
        qDebug() << QString("Error : %1.").arg(m_serial->errorString());
        qDebug() << ("Open error!");
    }
}

void RS232::closeSerialPort()
{
    if (m_serial->isOpen())
        m_serial->close();

    qDebug() << ("SerialPort disconnected");
}

void RS232::writeData(const QByteArray &data)
{
    const qint64 written = m_serial->write(data);
    if (written == data.size()) {
        m_bytesToWrite += written;
        m_timer->start(kWriteTimeout);
    } else {
        const QString error = tr("Failed to write all data to port %1.\n"
                                 "Error: %2").arg(m_serial->portName(),
                                       m_serial->errorString());
        qDebug() << (error);
    }
}

void RS232::readData()
{
    const QByteArray data = m_serial->readAll();
    //m_console->putData(data);
    qDebug() << data;
}

void RS232::handleError(QSerialPort::SerialPortError error)
{
    if (error == QSerialPort::ResourceError) {
        qDebug() << QString("Critical Error: %1").arg(m_serial->errorString());
        closeSerialPort();
    }
}

void RS232::handleBytesWritten(qint64 bytes)
{
    m_bytesToWrite -= bytes;
    if (m_bytesToWrite == 0)
        m_timer->stop();
}

void RS232::handleWriteTimeout()
{
    const QString error = tr("Write operation timed out for port %1.\n"
                             "Error: %2").arg(m_serial->portName(),
                                   m_serial->errorString());
    qDebug() << (error);
}

